/**
 * Copyright &copy; 2012-2013 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package com.featherlike.feather.generator;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.featherlike.feather.generator.config.ConfigProperties;
import com.featherlike.feather.generator.config.Constant;
import com.featherlike.feather.generator.db.DBKeyInfo;
import com.featherlike.feather.generator.db.MysqlKeyInfo;
import com.featherlike.feather.generator.engine.EngineFactory;
import com.featherlike.feather.generator.engine.ITemplateEngine;
import com.featherlike.feather.generator.entity.Column;
import com.featherlike.feather.generator.entity.Field;
import com.featherlike.feather.generator.entity.Table;
import com.featherlike.feather.generator.excel.ExcelContext;
import com.featherlike.framework.common.util.MapUtil;
import com.featherlike.framework.common.util.StringUtil;

/**
 * @author WYY
 * @description
 */
public class GeneratorImpl implements IGenerator {
    /**log**/
    private static Logger logger = LoggerFactory.getLogger(GeneratorImpl.class);
    /**config**/
    private GeneratorCfgImpl generatorCfg = GeneratorCfgImpl.instance();
    /**tempEngine**/
    private ITemplateEngine tmplEngine = EngineFactory.getInstance().getTemplateEngine(ConfigProperties.getTemlateEngine());
    /**数据库信息适配，如关键字、字段映射等**/
    private DBKeyInfo dbKeyInfo = MysqlKeyInfo.instance();

    /**
     * 读取excel获取Map信息
     * @return Map<表名,List<字段>>
     */
    public Map<Table, List<Column>> getTableMapFromExcel() {
        return ExcelContext.getInstance().getTableMapFromExcel(generatorCfg.getExcelPath());
    }

    /**
     * 生成SQL
     * @param dataMap Map信息
     * @throws IOException IO异常
     */
    private void generateSQL(Map<String, Object> dataMap) throws IOException {
        String tmplPath = Constant.TABLE + tmplEngine.getTemplateSuffix();
        String filePath = generatorCfg.getSqlPath(((Table) dataMap.get(Constant.KEY_TABLE)).getName());
        tmplEngine.mergeTemplateIntoFile(tmplPath, dataMap, filePath);
        logger.info("Table: {}", filePath);
    }

    /**
     * 生成Java代码
     * @param dataMap Map信息
     * @param classType 类
     * @throws IOException IO异常
     */
    private void generateJava(Map<String, Object> dataMap, String classType)
            throws IOException {
        String tmlpPath = classType + tmplEngine.getTemplateSuffix();
        String filePath = generatorCfg.getJavaPath((String) dataMap.get(Constant.KEY_CLASSNAME), classType);
        tmplEngine.mergeTemplateIntoFile(tmlpPath, dataMap, filePath);
        logger.info("Java: {}", filePath);
    }

    /**
     * 生成mapper.xml
     * @param dataMap Map信息
     * @param mapper mapper
     */
    private void generateMapper(Map<String, Object> dataMap, String mapper) {
        String tmlpPath = mapper + tmplEngine.getTemplateSuffix();
        String filePath = generatorCfg.getJavaPath((String) dataMap.get(Constant.KEY_CLASSNAME), mapper);
        tmplEngine.mergeTemplateIntoFile(tmlpPath, dataMap, filePath);
        logger.info("Java: {}", filePath);
    }

    /**
     * 生成视图层代码
     * @param dataMap Map信息
     * @param viewType 视图类型
     * @throws IOException IO异常
     */
    private void generateView(Map<String, Object> dataMap, String viewType)
            throws IOException {
        String tmplPath = Constant.VIEW + viewType
                + tmplEngine.getTemplateSuffix();
        String filePath = generatorCfg.getViewPath((String) dataMap.get(Constant.KEY_CLASSNAME), viewType);
        tmplEngine.mergeTemplateIntoFile(tmplPath, dataMap, filePath);
        logger.info("View: {}", filePath);
    }

    private List<Map<String, Object>> getDataMaps(
            Map<Table, List<Column>> tableMap) {
        List<Map<String, Object>> dataMaps = new ArrayList<Map<String, Object>>();

        for (Map.Entry<Table, List<Column>> entry : tableMap.entrySet()) {
            Table table = entry.getKey();
            // 表名
            String tableName = table.getName();
            // 类名-首字母为小写
            String className = StringUtil.toCamelhump(tableName
                    .substring(tableName.indexOf("_") + 1));

            List<Column> columnList = entry.getValue();
            List<Field> fieldList = transformFieldList(columnList);
            Map<String, Object> dataMap = MapUtil.newHashMap();

            dataMap.put(Constant.KEY_TABLE, table);
            dataMap.put("columnList", columnList);
            dataMap.put(Constant.KEY_CLASSNAME, className);
            dataMap.put("fieldList", fieldList);
            dataMap.put("StringUtil", new StringUtil());
            dataMap.putAll(generatorCfg.getModel(className));

            dataMaps.add(dataMap);
        }
        return dataMaps;
    }

    /**
     * @description 生成所有文件
     * @updated by WYY 2013年11月24日 下午3:41:36
     * @param tableMap 通过Map信息
     * @throws IOException IO异常
     */
    public void generateAll(Map<Table, List<Column>> tableMap) throws IOException {
        logger.info("--------------Generate start------------------");
        if (StringUtil.isBlank(generatorCfg.getPackageName())
                || StringUtil.isBlank(generatorCfg.getModuleName())
                || StringUtil.isBlank(generatorCfg.getFunctionName())) {
            logger.error("参数设置错误：包名、模块名、类名、功能名不能为空。");
            return;
        }
        List<Map<String, Object>> dataMaps = getDataMaps(tableMap);
        for (Map<String, Object> dataMap : dataMaps) {
            // 生成Entity
            //generateJava(dataMap, Constant.ENTITY);
            // 生成DAO
            //generateJava(dataMap, Constant.DAO);
            // 生成Service
            //generateJava(dataMap, Constant.SERVICE);
            // 生成Controller
            //generateJava(dataMap, Constant.CONTROLLER);
            //generateMapper(dataMap, Constant.MAPPER);
            // 生成viewForm
            //generateView(dataMap, Constant.VIEW_FORM);
            // 生成viewList
            //generateView(dataMap, Constant.View_LIST);
            // 生成sql
            generateSQL(dataMap);
            logger.info("-----------------HLL-------------------------");
        }
        logger.info("------------Generate completely--------------");
    }



    /**
     * 生成sql
     * @param tableMap Map信息
     * @throws IOException IO异常
     */
    public void generateAllSQL(Map<Table, List<Column>> tableMap)
            throws IOException {
        List<Map<String, Object>> dataMaps = getDataMaps(tableMap);
        for (Map<String, Object> dataMap : dataMaps) {
            generateSQL(dataMap);
        }
    }

    /**
     * 生成java类
     * @param tableMap Map信息
     * @throws IOException IO异常
     */
    public void generateAllJava(Map<Table, List<Column>> tableMap)
            throws IOException {
        List<Map<String, Object>> dataMaps = getDataMaps(tableMap);
        for (Map<String, Object> dataMap : dataMaps) {
            // 生成Entity
            generateJava(dataMap, Constant.ENTITY);
            // 生成DAO
            generateJava(dataMap, Constant.DAO);
            // 生成Service
            generateJava(dataMap, Constant.SERVICE);
            // 生成Controller
            generateJava(dataMap, Constant.CONTROLLER);
            // 生成viewForm
            generateView(dataMap, Constant.VIEW_FORM);
            // 生成viewList
            generateView(dataMap, Constant.View_LIST);
        }
    }

    /**
     * 将所有列数据转换成字段
     * @param columnList 列集合
     * @return 字段集合
     */
    private List<Field> transformFieldList(List<Column> columnList) {
        List<Field> fieldList = new ArrayList<Field>(columnList.size());
        for (Column column : columnList) {
            String fieldName = dbKeyInfo.transformFieldName(column.getName());
            String fieldType = dbKeyInfo.transformFieldType(column.getType());
            String fieldComment = column.getComment();
            String fieldLength = column.getLength();
            String listPage = column.getListPage();
            String queryPage = column.getQueryPage();
            String modifyPage = column.getModifyPage();
            String asLink = column.getAsLink();
            String dictType = column.getDictType();
            fieldList.add(
                new Field(fieldName, fieldType, fieldComment, Integer.parseInt(fieldLength), listPage, queryPage, modifyPage, asLink, dictType)
            );
        }
        return fieldList;
    }



}
